package com.pb.metadata.controller;

import com.pb.metadata.service.MateCodeValueService;
import com.pb.infra.oth.entity.common.Page;
import com.pb.infra.oth.entity.common.Result;
import com.pb.infra.oth.util.*;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 码值管理模块
 * @author liurongjun
 * @date 2021/02/22
 */
@Slf4j
@RestController
@RequestMapping("v1/metadata/mateCodeValueController")
public class MateCodeValueController {

    /**
     * 业务逻辑对象
     */
    @Resource
    private MateCodeValueService mateCodeValueService;

    /**
     * 日志操作表
     */
    private static final String TABLE_NAME = "PARAM_CODE_TYPE";

    /**
     * 日志操作功能名
     */
    private static final String OPERATION_MENU = "码值管理";

    /**
     * jwttoken配置类
     */
    @Resource
    private JwtTokenConfig jwtTokenConfig;

    /**
     * 查询分页数据
     *
     * @param map     查询参数
     * @param page    页码
     * @return Result 返回数据
     */
    @GetMapping("selectByPage")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result selectByPage(@RequestParam Map<String, Object> map, Page page, HttpServletRequest request) {
        return mateCodeValueService.selectByPage(map, page, request);
    }

    /**
     * 查询码值存储类型
     *
     * @return Result 返回数据
     */
    @GetMapping("getCodeStoreList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getCodeStoreList() {
        return mateCodeValueService.getCodeStoreList();
    }

    /**
     * 查询码值存储类型
     *
     * @return Result 返回数据
     */
    @GetMapping("getDataStoreList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getDataStoreList() {
        return mateCodeValueService.getDataStoreList();
    }

    /**
     * 查询码值对象名
     *
     * @return Result 返回数据
     */
    @GetMapping("getCodeTableList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getCodeTableList() {
        return mateCodeValueService.getCodeTableList();
    }

    /**
     * 保存码值相关信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("insert")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.ADD, menuName = OPERATION_MENU)
    public Result insert(@RequestBody Map<String, Object> paramMap, HttpServletRequest request) {
        Result insert = mateCodeValueService.insert(paramMap, request);
        return insert;
    }

    /**
     * 修改码值相关信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("update")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result update(@RequestBody Map<String, Object> paramMap, HttpServletRequest request){
        return mateCodeValueService.update(paramMap, request);
    }

    /**
     * 删除码值相关信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("delete")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.DEL, menuName = OPERATION_MENU)
    public Result delete(@RequestBody List<Map<String, Object>> paramMap) {
        mateCodeValueService.delete(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 启用停用相应码值
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("startOrStop")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result startOrStop(@RequestBody  List<Map<String,Object>> paramMap){
        mateCodeValueService.startOrStop(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 锁定码值相关信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("lockedBatch")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result lockedDate(@RequestBody List<String> paramMap) {
        mateCodeValueService.lockedDate(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 提交码值相关信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("freeBatch")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result freeDate(@RequestBody List<String> paramMap) {
        mateCodeValueService.freeDate(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 查询迭代码值信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @GetMapping("getIterDataList")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.QUERY, menuName = OPERATION_MENU)
    public Result getIterDataList(@RequestParam Map<String, Object> paramMap, Page page) {
        return mateCodeValueService.getIterDataList(paramMap, page);
    }

    /**
     * 新增迭代码值信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("saveIter")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.ADD, menuName = OPERATION_MENU)
    public Result saveIter(@RequestBody Map<String,Object> paramMap){
        Result insert = mateCodeValueService.saveIter(paramMap);
        return insert;
    }

    /**
     * 修改迭代码值信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("updateIter")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result updateIter(@RequestBody Map<String,Object> paramMap){
        return mateCodeValueService.updateIter(paramMap);
    }

    /**
     * 删除迭代码值信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("deleteIterBatch")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.DEL, menuName = OPERATION_MENU)
    public Result deleteIterBatch(@RequestBody Map<String, Object> paramMap) {
        mateCodeValueService.deleteIterBatch(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     *启用/停用迭代值信息
     *
     * @param paramMap 请求参数
     * @return Result 返回数据
     */
    @PostMapping("stopOrStartIterBatch")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.MOD, menuName = OPERATION_MENU)
    public Result stopOrStartIterBatch(@RequestBody Map<String, Object> paramMap) {
        mateCodeValueService.stopOrStartIterBatch(paramMap);
        return Result.OK_EMPTY;
    }

    /**
     * 导出码值信息EXCEL
     *
     * @param paramMap 请求参数
     * @param request  请求参数
     * @throws Exception
     */
    @PostMapping("exportCodeExcel")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.DOWN, menuName = OPERATION_MENU)
    public Map<String, Object> exportCodeExcel(@RequestBody  Map<String, Object> paramMap, HttpServletRequest request){
        String token = request.getHeader(jwtTokenConfig.getHeader());
        List<Map<String,Object>> dataList =  mateCodeValueService.selectSheet1(paramMap);
        List<Map<String,Object>> dataListRec = dataList.size() > 0 ? mateCodeValueService.selectSheetRecOrCommon(dataList) : null;
        String[][] sheeHeader={{"码表名称", "码值类型", "码值描述", "存放方式", "数据类型", "有效标识", "排序标识", "法人编号", "法人名称", "备注"},
                {"码值类型", "业务描述", "业务码值", "上层业务码值", "叶子标识", "有效标识", "排序标识", "备注"}};
        String[][] sheetColumn={{"tableNames","businessCodeType","cnNames","codeStoreDesc","dataStoreType","activeDesc","orderFlag", "corpId", "corpName", "remark"},
                {"businessCodeType","title","businessCode","upBusinessCode","leafFlag","activeDesc","orderFlag","remarks"}};
        String[][] sheetComments={{"必须指定数据库用户和表名","","","存放方式：展平码表，递归码表","数据类型：字符串，数字，时间","有效标识：启用，停用","","","",""},
                {"","","码表数据类型为数字时，业务码值请输入数值类型","上层业务码值不为空则必须存在，且按层级顺序填写","叶子标识：叶子，目录","有效标识：启用，停用","",""}};
        String[][] dataType = {{"STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING"},
                {"STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING"}};
        Object[] sheetData = {dataList,dataListRec};
        String[] sheetName={"码值类型信息","码值配置信息"};
        paramMap.put("jobBookName",sheetName);
        paramMap.put("title",sheeHeader);
        paramMap.put("order",sheetColumn);
        paramMap.put("comments",sheetComments);
        paramMap.put("data",sheetData);
        paramMap.put("token",token);
        paramMap.put("dataType",dataType);
        paramMap.put("fileName","码值信息");
        return  paramMap;
    }

    /**
     * 导入码值信息EXCEL
     *
     * @param paramMap    请求参数
     * @param multRequest 请求参数
     * @param request     请求参数
     * @return Map 返回数据
     */
    @PostMapping("importCodeExcel")
    @SysLog(tableName = TABLE_NAME, action = Constant.ACTION_NAME.UP, menuName = OPERATION_MENU)
    public Map<String, Object> importIndex(@RequestParam Map<String, Object> paramMap,MultipartHttpServletRequest multRequest, HttpServletRequest request) {
        Map<String, Object> responseMap = new HashMap<>();
        String token = request.getHeader(jwtTokenConfig.getHeader());
        Claims claims = jwtTokenConfig.getClaimByToken(token);
        String userId = (String)claims.get(jwtTokenConfig.getSub());
        InputStream input = null;
        Object checkResOrCommMap = null;
        Map<String, Object> mainCheckList = null;
        try {
            MultipartFile excelFile = multRequest.getFile("excel-file");
            input = excelFile.getInputStream();
            XSSFWorkbook workbook = new XSSFWorkbook(input);
            //组装第一个SHEET(所有)
            ArrayList<String[]> colInfos = new ArrayList<>();
            String[] colNames = {"码表名称", "码值类型", "码值描述", "存放方式", "数据类型", "有效标识", "排序标识", "法人编号", "法人名称", "备注"};
            String[] colNulls = {"NOTNULL", "NOTNULL", "NOTNULL", "NOTNULL", "NOTNULL", "NOTNULL", "NOTNULL", "NULL", "NULL", "NULL"};
            String[] colConstraints = {"NO", "CONSTRAINTS_1", "NO", "NO", "NO", "NO", "NO", "NO", "NO", "NO"};
            String[] colValueLimits = {"tableList_upper", "stringValue", "", "递归码表-展平码表", "字符串-数字-时间", "启用-停用", "", "", "", ""};
            colInfos.add(colNames);
            colInfos.add(colNulls);
            colInfos.add(colConstraints);
            colInfos.add(colValueLimits);
            Object checkMap = mateCodeValueService.checkCodeExcelData(workbook, 10, colInfos);
            //组装递归/展平码表导入
            if (!(checkMap instanceof String)){
                mainCheckList = (Map) checkMap;
                List<String> appAndBussList = (ArrayList)mainCheckList.get("appAndBussList");
                Map<String, Object> bussCodeType = (Map) mainCheckList.get("bussCodeType");
                ArrayList<String[]> colResInfos = new ArrayList<>();
                String[] colResNames = {"码值类型", "业务描述", "业务码值", "上层业务码值", "叶子标识", "有效标识", "排序标识", "备注"};
                String[] colResNulls = {"NOTNULL", "NOTNULL", "NOTNULL", "NULL", "NOTNULL", "NOTNULL", "NOTNULL", "NULL"};
                String[] colResConstraints = {"CONSTRAINTS_0", "NO", "CONSTRAINTS_0_2", "NO", "NO", "NO", "NO", "NO"};
                String[] colResValueLimits = {"", "", "mapValid", "parentList", "目录-叶子", "启用-停用", "", ""};
                colResInfos.add(colResNames);
                colResInfos.add(colResNulls);
                colResInfos.add(colResConstraints);
                colResInfos.add(colResValueLimits);
                checkResOrCommMap = mateCodeValueService.checkResAndComExcelData(workbook, 8, colResInfos, appAndBussList, bussCodeType);
            }
            if (checkMap instanceof String) {
                //检查未通过
                responseMap.put("code", -1);
                responseMap.put("msg", checkMap.toString());
            } else if (checkResOrCommMap instanceof  String){
                //检查未通过
                responseMap.put("code", -1);
                responseMap.put("msg", checkResOrCommMap.toString());
            } else {
                //检查通过
                Map<String, Object> checkResOrCommList = (Map) checkResOrCommMap;
                Map<String, Object> checkList = (Map) checkMap;
                mateCodeValueService.doImportCodeExcelData(checkList,checkResOrCommList,userId);
                String rightInfo = mainCheckList.get("rightInfo").toString() + checkResOrCommList.get("rightInfo").toString();
                responseMap.put("code", 0);
                responseMap.put("msg", rightInfo);
            }
        } catch (Exception e) {
            responseMap.put("code", -1);
            responseMap.put("msg", "导入失败");
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException e) {
                responseMap.put("code", -1);
                responseMap.put("msg", "导入失败");
                log.error("关闭文件流失败", e);
            }
        }
        return responseMap;
    }

}
